package com.ndood.admin.service.system.impl;

import java.util.ArrayList;
import java.util.List;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.ndood.admin.core.util.JPAUtil;
import com.ndood.admin.pojo.system.RegionPo;
import com.ndood.admin.pojo.system.dto.RegionDto;
import com.ndood.admin.repository.system.RegionRepository;
import com.ndood.admin.repository.system.manager.RegionRepositoryManager;
import com.ndood.admin.service.system.SystemRegionService;

/**
 * 地区模块业务类
 */
@Transactional
@Service
public class SystemRegionServiceImpl implements SystemRegionService {
	
	@Autowired
	private RegionRepository regionDao;
	
	@Autowired
	private RegionRepositoryManager regionRepositoryManager;

	@Override
	public List<RegionDto> getRegionList(String keywords, Integer parentId) throws Exception {
		
		// Step1: 查询出所有满足条件的地区 
		List<RegionPo> poList = regionDao.findAll(new Specification<RegionPo>() {
			@Override
			public Predicate toPredicate(Root<RegionPo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				Predicate p = cb.conjunction();
				// Step1: 根据关键词搜索
				if(!StringUtils.isEmpty(keywords)){
					Predicate temp = cb.or(
						cb.like(root.get("name"), "%" + keywords + "%"),
						cb.like(root.get("pinyin"), "%" + keywords + "%"));
					p = cb.and(p, temp);
					return p;
				}
				// Step2: 加载顶级节点
				if(parentId==null){
					Predicate temp = cb.isNull(root.<RegionPo>get("parent").<Integer>get("id"));
					p = cb.and(p, temp);
					return p;
				}
				// Step3: 根据parentNode加载子节点
				Predicate temp = cb.equal(root.<RegionPo>get("parent").<Integer>get("id"), parentId);
				p = cb.and(p, temp);
				return p;
			}
		});
		
		// Step2: 将地区转换成dtoList
		List<RegionDto> dtoList = new ArrayList<RegionDto>();
		for (RegionPo po : poList) {
			RegionDto dto = new RegionDto();
			JPAUtil.fatherToChild(po, dto);
			
			// 是否是叶子节点
			Integer isLeaf = po.getIsLeaf();
			Integer pid = po.getParent()==null? null: po.getParent().getId();
			dto.setParentId(pid);
			dto.setIsLeaf(isLeaf);
			dtoList.add(dto);
		}
		return dtoList;
	
	}

	@Override
	public void batchDeleteRegion(Integer[] ids) {
		
		Integer pid = null;
		
		// Step1: 批量删除
		for (int i=0;i<ids.length;i++) {
			if(i==0) {
				RegionPo po = regionDao.findById(ids[i]).get();
				RegionPo parent = po.getParent();
				if(parent!=null) {
					pid = parent.getId(); // 没有触发延迟加载
				}
			}
			regionDao.deleteById(ids[i]);
		}
		
		// Step2: 如果父节点下面已经没有子节点，则更新父节点为叶子节点
		if(pid == null) {
			return;
		}
		Long childrenCount = regionRepositoryManager.countChildrenByParentId(pid);
		if(childrenCount==0) {
			RegionPo parent = regionDao.findById(pid).get();
			parent.setIsLeaf(1);
			regionDao.save(parent);
		}
	}

	@Override
	public RegionDto addRegion(RegionDto dto) throws Exception {
		
		// Step1: 处理parentId
		RegionPo po = new RegionPo();
		Integer parentId = dto.getParentId();
		if (parentId != null) {
			RegionPo parent = regionDao.findById(parentId).get();
			parent.setIsLeaf(0);
			po.setParent(parent);
		}
		
		// Step2: 处理额外字段
		dto.setIsLeaf(1);

		// Step3: 保存并返回
		JPAUtil.childToFather(dto, po);
		po = regionDao.save(po);
		dto.setId(po.getId());
		return dto;
	
	}

	@Override
	public RegionDto getRegion(Integer id) throws Exception {
		
		RegionDto dto = new RegionDto();
		RegionPo po = regionDao.findById(id).get();
		JPAUtil.fatherToChild(po, dto);
		dto.setParent(po.getParent());
		return dto;
	
	}

	@Override
	public RegionDto updateRegion(RegionDto dto) throws Exception {
	
		RegionPo po = regionDao.findById(dto.getId()).get();
		JPAUtil.childToFather(dto, po);
		regionDao.save(po);
		
		dto.setIsLeaf(dto.getIsLeaf());
		return dto;
	
	}

	@Override
	public List<RegionDto> getProvinceList(String provinceId) throws Exception {
		
		// Step1: 查询出所有满足条件的地区 
		List<RegionPo> poList = regionDao.findAll(new Specification<RegionPo>() {
			@Override
			public Predicate toPredicate(Root<RegionPo> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
				Predicate p = cb.conjunction();

				// 如果省sid不为空，则根据条件查询
				if(!StringUtils.isEmpty(provinceId)){
					Predicate temp = cb.equal(root.get("sid"), provinceId);
					p = cb.and(p, temp);
					return p;
				}
				
				// 如果省sid为空，则查找出所有的父节点为空的地区
				Predicate temp = cb.isNull(root.<RegionPo>get("parent").<Integer>get("id"));
				p = cb.and(p, temp);
				return p;
			}
		});
		
		// Step2: 将地区转换成dtoList
		List<RegionDto> pList = new ArrayList<RegionDto>();
		for (RegionPo p1 : poList) {
			// 加载省
			RegionDto province = new RegionDto();
			province.setSid(p1.getSid());
			province.setName(p1.getName());
			pList.add(province);
			if(StringUtils.isEmpty(provinceId)){
				continue;
			}
			
			// 加载市
			if(p1.getChildren()==null){
				continue;
			}
			List<RegionDto> cList = new ArrayList<RegionDto>();
			for (RegionPo p2 : p1.getChildren()) {
				RegionDto city = new RegionDto();
				city.setSid(p2.getSid());
				city.setName(p2.getName());
				cList.add(city);
				
				// 加载区
				if(p2.getChildren()==null){
					continue;
				}
				List<RegionDto> rList = new ArrayList<RegionDto>();
				for (RegionPo p3 : p2.getChildren()) {
					RegionDto region = new RegionDto();
					region.setSid(p3.getSid());
					region.setName(p3.getName());
					rList.add(region);
				}
				city.setList(rList);
			}
			province.setList(cList);
		}
		return pList;
	
	}
}
